package game.engine.base.dev

import game.engine.base.CoreUtil
import java.lang.RuntimeException
import java.lang.StringBuilder
import kotlin.math.cos
import kotlin.math.sin

/**
 *
 *  | m0,m3,m6 |
 *  | m1,m4,m7 |
 *  | m2,m5,m8 |
 *
 */
class Mat3 (
    var m0:Float = 1f,
    var m1:Float = 0f,
    var m2:Float = 0f,
    var m3:Float = 0f,
    var m4:Float = 1f,
    var m5:Float = 0f,
    var m6:Float = 0f,
    var m7:Float = 0f,
    var m8:Float = 1f,
        ){

    companion object{

        // 返回一个新的 Mat3
        fun multiply(lhs:Mat3,rhs: Mat3):Mat3{
            return Mat3().copyFrom(lhs).multiply(rhs)
        }
    }

    // 返回自己
    fun copyFrom(mat:Mat3):Mat3{
        m0 = mat.m0
        m1 = mat.m1
        m2 = mat.m2
        m3 = mat.m3
        m4 = mat.m4
        m5 = mat.m5
        m6 = mat.m6
        m7 = mat.m7
        m8 = mat.m8
        return this
    }

    // 返回自己
    fun identity():Mat3{
        m0 = 1f
        m1 = 0f
        m2 = 0f
        m3 = 0f
        m4 = 1f
        m5 = 0f
        m6 = 0f
        m7 = 0f
        m8 = 1f
        return this
    }

    // 返回自己
    fun multiply(rhs:Mat3):Mat3{
        val n0 = m0 * rhs.m0 + m3 * rhs.m1 + m6 * rhs.m2
        val n1 = m1 * rhs.m0 + m4 * rhs.m1 + m7 * rhs.m2
        val n2 = m2 * rhs.m0 + m5 * rhs.m1 + m8 * rhs.m2

        val n3 = m0 * rhs.m3 + m3 * rhs.m4 + m6 * rhs.m5
        val n4 = m1 * rhs.m3 + m4 * rhs.m4 + m7 * rhs.m5
        val n5 = m2 * rhs.m3 + m5 * rhs.m4 + m8 * rhs.m5

        val n6 = m0 * rhs.m6 + m3 * rhs.m7 + m6 * rhs.m8
        val n7 = m1 * rhs.m6 + m4 * rhs.m7 + m7 * rhs.m8
        val n8 = m2 * rhs.m6 + m5 * rhs.m7 + m8 * rhs.m8

        m0 = n0
        m1 = n1
        m2 = n2
        m3 = n3
        m4 = n4
        m5 = n5
        m6 = n6
        m7 = n7
        m8 = n8
        return this
    }

    // 返回自己
    fun inverse():Mat3{
        val a00 = m0
        val a01 = m1
        val a02 = m2

        val a10 = m3
        val a11 = m4
        val a12 = m5

        val a20 = m6
        val a21 = m7
        val a22 = m8

        val b01 = a22 * a11 - a12 * a21
        val b11 = -a22 * a10 + a12 * a20
        val b21 = a21 * a10 - a11 * a20

        // Calculate the determinant
        var det = a00 * b01 + a01 * b11 + a02 * b21;

        if (det == 0f) {
            throw RuntimeException("矩阵行列式为0,不存在逆矩阵.")
        }
        det = 1.0f / det

        m0 = b01 * det
        m1 = (-a22 * a01 + a02 * a21) * det
        m2 = (a12 * a01 - a02 * a11) * det
        m3 = b11 * det
        m4 = (a22 * a00 - a02 * a20) * det
        m5 = (-a12 * a00 + a02 * a10) * det
        m6 = b21 * det
        m7 = (-a21 * a00 + a01 * a20) * det
        m8 = (a11 * a00 - a01 * a10) * det
        return  this
    }

    fun loadTRS(x:Float,y:Float,degress:Float,sx:Float,sy:Float):Mat3{
        val rad = CoreUtil.toRad(degress)
        val cos = cos(rad)
        val sin = sin(rad)
        m0 = cos * sx
        m1 = sin * sx
        m2 = 0f
        m3 = -sin * sy
        m4 = cos * sy
        m5 = 0f
        m6 = x
        m7 = y
        m8 = 1f
        return  this
    }
}

fun Mat3.debug_string():String{
    val sb = StringBuilder()
    sb.append("| $m0,$m3,$m6 |\n")
    sb.append("| $m1,$m4,$m7 |\n")
    sb.append("| $m2,$m5,$m8 |\n")
    return  sb.toString()
}